﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace NTTDATA.BEENChina.ResultCertification.Client.Entry.UI
{
    public partial class UserControlResult : UserControl
    {
        public int FontSize
        {
            get { return _fontSize; }
            set { _fontSize = value; }
        }

        private int _fontSize = 12;
 
        private int _lblSpan = 10;
        public int LblSpan
        {
            get { return _lblSpan; }
            set { _lblSpan = value; }
        }

        private int _colSpan = 20;
        public int ColSpan
        {
            get { return _colSpan; }
            set { _colSpan = value; }
        }

        private int _rowSpan = 4;
        //public int RowSpan
        //{
        //    get { return _rowSpan; }
        //    set { _rowSpan = value; }
        //}

        private int _contentLeft = 10;
        public int ContentLeft
        {
            get { return _contentLeft; }
            set { _contentLeft = value; }
        }

        private int _contentTop = 10;
        public int ContentTop
        {
            get { return _contentTop; }
            set { _contentTop = value; }
        }

        public List<List<string>> EntryReult { get; set; }

        public string Entryformat
        {
            get
            {
                int idx = _entryFormat.IndexOf("\\");
                string subFormat = idx == -1 ? this._entryFormat : _entryFormat.Substring(0, idx);
                return subFormat;
            }
            set
            {
                _entryFormat = value;
            }
        }private string _entryFormat = string.Empty;

        public Dictionary<string, string> GridItems { get; set; }

        public string ResultFormate { get; set; }
        public string SplitFormat { get; set; }

        private Dictionary<string, Size> labelSize = new Dictionary<string, Size>();
        private Dictionary<string, string> labelText = new Dictionary<string, string>();

        public UserControlResult()
        {
            InitializeComponent();
            initLableSize();
            initLabelText();


        }

        private void initLableSize()
        {
            //年号  
            labelSize.Add("gg", new Size(40, 20));
            //年
            labelSize.Add("yy", new Size(40, 20));
            labelSize.Add("yyyy", new Size(40, 20));
            //月
            labelSize.Add("MM", new Size(40, 20));
            //日
            labelSize.Add("dd", new Size(40, 20));
            //文字
            labelSize.Add("tx", new Size(100, 20));
            //入退院区分
            labelSize.Add("hp", new Size(40, 20));
            //上下午
            labelSize.Add("tt", new Size(40, 20));
            //时
            labelSize.Add("HH", new Size(20, 20));
            //时
            labelSize.Add("hh", new Size(20, 20));

            //            
            labelSize.Add("tel", new Size(120, 20));
            //            
            labelSize.Add("tel_a", new Size(60, 20));
            //        
            labelSize.Add("tel_b", new Size(60, 20));
            //            
            labelSize.Add("tel_c", new Size(60, 20));

            //            
            labelSize.Add("d", new Size(120, 20));
            //            
            labelSize.Add("md", new Size(120, 20));
            //        
            labelSize.Add("ed", new Size(120, 20));
            //
            labelSize.Add("sel", new Size(240, 20));

            labelSize.Add("kana", new Size(120, 20));

            labelSize.Add("kannji", new Size(120, 20));

            labelSize.Add("postalcode", new Size(120, 20));
            labelSize.Add("prefecture", new Size(120, 20));
            labelSize.Add("city", new Size(120, 20));
            labelSize.Add("town", new Size(120, 20));
            labelSize.Add("number&mansion", new Size(240, 20));


            labelSize.Add("bm",   new Size(240, 20));
            labelSize.Add("blm", new Size(240, 20));
            labelSize.Add("yym", new Size(240, 20));
            labelSize.Add("ssm", new Size(240, 20));
            labelSize.Add("wly", new Size(240, 20));
            labelSize.Add("km", new Size(240, 20));
            labelSize.Add("yjm", new Size(240, 20));
            labelSize.Add("hsm", new Size(240, 20));
            labelSize.Add("bmm", new Size(240, 20));
            labelSize.Add("zwm", new Size(240, 20));
            labelSize.Add("jrjg", new Size(240, 20));
            labelSize.Add("dm", new Size(240, 20));
            labelSize.Add("gm", new Size(240, 20));
            labelSize.Add("spm", new Size(240, 20));
    　
            labelSize.Add("number", new Size(240, 20));
            labelSize.Add("kj", new Size(240, 20));
            labelSize.Add("xl", new Size(240, 20));

        }

        private void initLabelText()
        {
            labelText.Add("gg", "元号");
            labelText.Add("yy", "年");
            labelText.Add("yyyy", "年");
            labelText.Add("MM", "月");
            labelText.Add("dd", "日");
            labelText.Add("tx", "文字列");
            labelText.Add("hp", "入退院");
            labelText.Add("tt", "上下午");
            labelText.Add("HH", "時");
            labelText.Add("hh", "時");
            labelText.Add("mm", "分");

            labelText.Add("tel", "電話番号");
            labelText.Add("tel_a", "市外区番");//市外局　　市内局　　番号
            labelText.Add("tel_b", "市内区番");
            labelText.Add("tel_c", "番号");

            labelText.Add("d", "数値");
            labelText.Add("md", "数値");
            labelText.Add("ed", "英数");

            labelText.Add("sel", "選択");

            labelText.Add("kana", "仮名");
            labelText.Add("kannji", "漢字");

            labelText.Add("postalcode", "郵便");
            labelText.Add("prefecture", "県");
            labelText.Add("city", "市");
            labelText.Add("town", "町");
            labelText.Add("number&mansion", "番号　マンション");

            labelText.Add("bm", "病名");
            labelText.Add("blm","病理名");
            labelText.Add("yym","医院名");
            labelText.Add("ssm", "手术名");
            labelText.Add("wly","外来语");
            labelText.Add("km","科名");
            labelText.Add("yjm","薬剤");
            labelText.Add("hsm","会社");
            labelText.Add("bmm","所属");
            labelText.Add("zwm","役职");
            labelText.Add("jrjg","金融机关");
            labelText.Add("dm","地名");
            labelText.Add("gm","国名");;
            labelText.Add("spm","商品名");
　
            labelText.Add("number", "番号");
            labelText.Add("kj", "kj");
            labelText.Add("xl", "线量");
        }

        private Label GetLabel(string key)
        {
            Label modelLabel = new Label()
            {
                //Margin = new Padding(3, 1, 3, 1),
                AutoSize = false,
                TextAlign = ContentAlignment.MiddleCenter,
                //Parent =this,
                Visible = false,
                Font = new Font("MS PGothic", _fontSize)
            };

            //Size lblSize = new Size(40, 20);
            //labelSize.TryGetValue(key, out lblSize);
            //string text = string.Empty ;
            //modelLabel.Size = lblSize;
            return modelLabel;
        }

        public void Clear()
        {
            this.BorderStyle = this.AutoSize ? System.Windows.Forms.BorderStyle.None : System.Windows.Forms.BorderStyle.FixedSingle;
            this.Height = this.AutoSize ? 0 : this.Height; 

            this.panelPaint.Invalidate();
        }
 
        private List<OutputElement> contents =null;


        public void Init()
        {

            try
            {
                contents = createElement();
                resizeElement(contents);
                resizeControl(contents);

                this.panelPaint.Invalidate();
            }
            catch (Exception ex)
            {
                
                throw ex;
            }

        }

        private List<OutputElement> createElement()
        {
            List<OutputElement> contentList = createContent();
            List<OutputElement> headList = createHead();
            contentList.AddRange(headList);
            return contentList;
        }

        private List<OutputElement> createContent()
        {
            List<OutputElement> labelList = new List<OutputElement>();
            for (int i = 0; i < this.EntryReult.Count; i++)
            {
                for (int j = 0; j < this.EntryReult[i].Count; j++)
                {
                    List<OutputElement> elementList = createContentLable(this.EntryReult[i][j]);
                    elementList.ForEach(p =>
                    {
                        p.row = i + 1;
                        p.col = j;
                    });
                    labelList.AddRange(elementList);
                }
            }

            return labelList;
        }

        private List<OutputElement> createContentLable(string colText)
        {
            List<OutputElement> labelList = new List<OutputElement>();
            string[] formats = this.Entryformat.Split(new char[] { '/' });
            string[] entryResult = colText.Split(new char[] { '/' });

            for (int i = 0; i < formats.Length; i++)
            {
                if (i >= entryResult.Count())
                {
                    break;
                }
                OutputElement element = new OutputElement();
                string formate = formats[i];
                element.lbl = GetLabel(formate);
                //setlabelText(colText, element.lbl, formate, isText);
                element.lbl.Text = formate != "sel" ? entryResult[i] : appendSelName(formate, entryResult[i]);
                setlabelProperty(element.lbl, false);

                element.z = i;

                labelList.Add(element);
            }
            return labelList;
        }

        private string appendSelName(string formate, string val)
        {
            return val;
        //    if (GridItems == null)
        //    {
        //        return val;
        //    }

        //    string[] valArray = val.Split(new char[] { '.' });
        //    for (int i = 0; i < valArray.Count(); i++)
        //    {
        //        string selName = "";
        //        GridItems.TryGetValue(valArray[i], out selName);
        //        valArray[i] = string.IsNullOrEmpty(selName) ? valArray[i] : valArray[i] + " 【 " + selName + " 】 ";
        //    }
        //    return string.Join(".", valArray);
        }


        private List<OutputElement> createHead()
        {
            List<OutputElement> labelList = new List<OutputElement>();
            int colCount = 0;

            if (this.EntryReult.Count > 0)
            {
                colCount = this.EntryReult.Max(o => o.Count());
            }

            for (int i = 0; i < colCount; i++)
            {
                List<OutputElement> elementList = createHeadLable(i);
                elementList.ForEach(p =>
                {
                    p.row = 0;
                    p.col = i;
                });
                labelList.AddRange(elementList);
            }
            return labelList;
        }


        private List<OutputElement> createHeadLable(int colIndex)
        {
            List<OutputElement> labelList = new List<OutputElement>();
            string[] formats = this.Entryformat.Split(new char[] { '/' });

            List<string> col = this.EntryReult.Select(o => { return o.Count() > colIndex ? o[colIndex] : null; }).ToList();

            int maxColCount = 0;
            
            if (col.Count>0)
            {
                maxColCount = col.Max(o => { return o != null ? o.Split(new char[] { '/' }).Count() : 0; });
            }

            for (int i = 0; i < formats.Length; i++)
            {
                if (i >= maxColCount)
                {
                    break;
                }
                OutputElement element = new OutputElement();
                string formate = formats[i];
                element.lbl = GetLabel(formate);
                //setlabelText(colText, element.lbl, formate, isText);
                string text = "";
                
                labelText.TryGetValue(formate, out text);
                
                
                element.lbl.Text = text;
                setlabelProperty(element.lbl, true);

                element.z = i;

                labelList.Add(element);
            }
            return labelList;
        }

        private void resizeElement(List<OutputElement> labelList)
        {
            int maxCol = 0;
            
            if (labelList.Count>0)
            {
                maxCol = labelList.Max(o => o.col);
            }

            for (int i = 0; i <= maxCol; i++)
            {
                int maxZ = 0;

                if (labelList.Count > 0)
                {
                    maxZ = labelList.Max(o => { return o.col == i ? o.z : 0; });
                }

                for (int j = 0; j <= maxZ; j++)
                {
                    int maxLen = 0;

                    if (labelList.Count>0)
                    {
                        maxLen = labelList.Max(o => { return o.col == i && o.z == j ? o.lbl.Width : 0; });
                    }

                    labelList.ForEach(o =>
                    {
                        if (o.col == i && o.z == j)
                            o.lbl.Width = maxLen;
                    });
                }
            }
        }

        private void resizeControl(List<OutputElement> labelList)
        {
            //ClearPant();
            int curLeft = this.ContentLeft;
            int curTop = this.ContentTop;
            int maxLeft = -1;
            int maxRow = 0;
            int lastRowBotton = 0;
            
            
            if (labelList.Count >0)
            {
                maxRow =  labelList.Max(o => o.row);
            }

            for (int i = 0; i <= maxRow; i++)
            {
                int maxCol = 0;
                
                if ( labelList.Count > 0)
                {
                    maxCol = labelList.Max(o => { return o.row == i ? o.col : 0; });
                }

                for (int j = 0; j <= maxCol; j++)
                {
                    int maxZ = 0;
                    
                    if (labelList.Count>0)

                    {
                        maxZ = labelList.Max(o => { return o.row == i && o.col == j ? o.z : 0; });
                    }

                    for (int z = 0; z <= maxZ; z++)
                    {
                        OutputElement element = labelList.FirstOrDefault(o => o.row == i && o.col == j && o.z == z);
                        if (element == null)
                        {
                            break;
                        }
                        var graphics = Graphics.FromHwnd(Handle);
                        SizeF resultSize = graphics.MeasureString(" ", element.lbl.Font);


                        element.lbl.Left = curLeft;
                        element.lbl.Top = curTop;
                        element.lbl.Height = (int)resultSize.Height + 2 ;

                        curLeft += element.lbl.Width + this.LblSpan;


                        if (z == maxZ)
                        {
                            

                            lastRowBotton = element.lbl.Location.Y +
                                            Math.Max(element.lbl.Height, (int)resultSize.Height);
                        }
                    }

                    curLeft += this.ColSpan;

                   
                }

                curTop = lastRowBotton + _rowSpan;

                //curTop += lastRowBotton + this.RowSpan;
                
                maxLeft = Math.Max(curLeft, maxLeft);
                curLeft = this.ContentLeft;
            }

            panelPaint.Top = 0;
            panelPaint.Left = 0;
            panelPaint.Width = maxLeft;
            panelPaint.Height =curTop;
            if (this.AutoSize)
            {                
                this.AutoScroll = false;
                this.Width = maxLeft;
                this.Height = curTop;
                Console.WriteLine("curTop :" + curTop);
                Console.WriteLine("ContentTop :" + ContentTop);
                Console.WriteLine("this.Height: " + this.Height);
            }
            else
            {
                this.AutoScroll = true;
            }
            //panelPaint.Width = this.Width ;
            //panelPaint.Height = this.Height ;
        }
        private void outPutElement(List<OutputElement> labelList)
        { 

            foreach (OutputElement element in labelList)
           {
               element.Draw(GetGraphics(),_fontSize);
           }

        }

        private void setlabelProperty(Label lbl, bool isText)
        {
            //lbl.AutoSize = false;
            Graphics g = Graphics.FromHwnd(lbl.Handle);
            SizeF Sz = g.MeasureString(lbl.Text, lbl.Font);
            g.Dispose();

            lbl.Width = (int)Sz.Width + lbl.Margin.Size.Width * 2 + 5;

            if (isText)
            {
                lbl.Font = new Font(new Font("MS PGothic", _fontSize), FontStyle.Bold);
                lbl.BackColor = Color.Transparent;
                lbl.BorderStyle = System.Windows.Forms.BorderStyle.None; ;
            }
            else
            {
                lbl.BackColor = Color.White;
                lbl.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            }
        }

        

        private Graphics GetGraphics()
        {
            return this.g;
        }

        private void panelPaint_Paint(object sender, PaintEventArgs e)
        {

            try
            {

         
                //this.panelPaint.Paint -= this.panelPaint_Paint;

                Console.WriteLine(DateTime.Now.ToString() + "  panelPaint_Paint");

                this.g = e.Graphics;

                if (this.EntryReult == null || this.EntryReult.Count() <= 0)
                {
                    //this.BorderStyle = this.AutoSize ? System.Windows.Forms.BorderStyle.None : System.Windows.Forms.BorderStyle.FixedSingle;
                    //this.Height = this.AutoSize ? 0 : this.Height;



                    //Pen blackPen = new Pen(Color.Black, 1);

                    //// Create rectangle.
                    //Rectangle rect = new Rectangle(0, 0, 1, 1);

                   // g.DrawRectangle(blackPen,rect);

                    return;
                }
         
                outPutElement(contents);
            }
            catch (Exception ex)
            {

                throw ex;
            }
           
           
        }

        private Graphics g = null;
 
    }

    public class OutputElement
    {

        public Label lbl;
        public int row;
        public int col;
        public int z;

        public void Draw(Graphics g,int fontSize)
        {
            try
            {
                
           
             Pen blackPen = new Pen(Color.Black, 1);
             Pen grayPen = new Pen(Color.DarkGray, 1);
             grayPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;

             System.Drawing.Font bodyFont = new System.Drawing.Font("MS PGothic", fontSize);
             System.Drawing.Font titleFont = new System.Drawing.Font("MS PGothic", fontSize, FontStyle.Bold);

            System.Drawing.SolidBrush drawBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black);
            //System.Drawing.StringFormat drawFormat = new System.Drawing.StringFormat();
            //drawFormat.FormatFlags = StringFormatFlags.DirectionVertical;
            //System.Drawing.SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(248, 233, 255));
            //g.FillRectangle(myBrush, new Rectangle(0, 0, lbl.Width, lbl.Height));



          
             
            // lbl.Font = bodyFont;
            if (String.IsNullOrEmpty(lbl.Text))
            {
                lbl.Text = @" ";
            }
 
           
           SizeF resultSize = g.MeasureString(lbl.Text, lbl.Font);
           int offset = (lbl.Height - (int)resultSize.Height) / 2;

            
           
           if (!String.IsNullOrEmpty(lbl.Text))
           {
               if (row > 0)
               {
                   g.DrawString(lbl.Text, bodyFont, drawBrush, lbl.Left + 2, lbl.Top + offset + 2);
               }
               else
               {
                   g.DrawString(lbl.Text, titleFont, drawBrush, lbl.Left + 2, lbl.Top + offset + 2);
               }
           }


        
            if (row > 0)
           {
              /* g.DrawRectangle(grayPen, new Rectangle(lbl.Left, lbl.Top,
                   Math.Max(lbl.Width, (int)resultSize.Width),
                   Math.Max(lbl.Height, (int)resultSize.Height)));*/
                
                g.DrawLine(grayPen,
                    new Point(lbl.Location.X, lbl.Top + lbl.Height),
                    new Point(lbl.Location.X + lbl.Width,lbl.Location.Y + lbl.Height));
           }

            bodyFont.Dispose();
            titleFont.Dispose();
            drawBrush.Dispose();

            //g.Dispose();
            //g = null;
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }
    }

    public class DrawPanel : System.Windows.Forms.Panel
    {
        public DrawPanel()
            : base()
        {
            //enable double buffering
            this.SetStyle(ControlStyles.UserPaint |
                          ControlStyles.AllPaintingInWmPaint |
                          ControlStyles.OptimizedDoubleBuffer, true);

            SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            this.BackColor = Color.Transparent;
        }
    }
}
